﻿namespace NJQuery {
	using System;
	using System.Web.UI;
	using System.Web.UI.WebControls;
	using System.Text;

	/// <summary>
	/// Uses <see cref="Control"/> to provide a standard base implementation of the <see cref="IManagedControl"/> contract requried by the <see cref="Manager"/> control to generate jQuery/JavaScript in addition to HTML markup typical of a control.
	/// </summary>
	[ParseChildren(true), PersistChildren(false)]
	public abstract class ManagedControl : Control, IManagedControl {


		#region Constants: Property defaults

		private const bool defaultUseCssSyling = false;

		#endregion


		#region Constructors

		/// <summary>
		/// Initializes a new instance of the <see cref="ManagedControl"/> base class.
		/// </summary>
		protected ManagedControl() { }

		#endregion


		#region Properties

		/// <summary>
		/// Gets or sets a value instructing the server control not to render style defined as HTML attributes on the element, rather requiring the site's stylesheet to handle functionality required to properly render the client UI.
		/// This value can be overridden at the <see cref="Manager"/> level rather than setting each individual control.
		/// </summary>
		public bool UseCssStyling {
			get { return ViewState["UseCssStyling"] as bool? ?? defaultUseCssSyling; }
			set { ViewState["UseCssStyling"] = value; }
		}

		/// <summary>
		/// Gets a value using the jQuery <see cref="Manager"/> as well as control itself that instructs the control not to render style as HTML attributes on the element, forcing the site developer to include the values in the site's stylesheet.
		/// This method is used primarily by control developers.
		/// </summary>
		protected bool MasterUseCssStyling {
			get {
				switch(Manager.GetCurrent(Page).UseCssStyling) {
					case MasterBoolean.ByControl: return UseCssStyling;
					case MasterBoolean.Always: return true;
					case MasterBoolean.Never: return false;
					default: return UseCssStyling;
				}
			}
		}

		/// <summary>
		/// Gets a <see cref="ControlCollection"/> object that represents the child controls for a specified server control in the UI hierarchy.
		/// </summary>
		public override sealed ControlCollection Controls {
			get { return base.Controls; }
		}

		/// <summary>
		/// Gets a <see cref="GroupedControlCollection"/> object that represents the grouped child controls for a server control in the UI hierarcy.
		/// </summary>
		protected virtual GroupedControlCollection GroupedControls {
			get { return (GroupedControlCollection)base.Controls; }
		}

		#endregion


		#region Methods: Grouped child controls

		/// <summary>
		/// Returns the collection of all controls that are contained in the <see cref="ManagedControl"/>.
		/// </summary>
		/// <returns>A <see cref="ControlCollection"/> object that consists of all controls that define the content of the <see cref="ManagedControl"/>.</returns>
		protected override sealed ControlCollection CreateControlCollection() {
			return new GroupedControlCollection(this);
		}

		#endregion


		#region Methods: Overrideable empty implementation of IManagedControl

		/// <summary>
		/// Renders the jQuery "Ready Event" script required to generate the client-side jQuery widget.
		/// This method is used primarily by control developers.
		/// </summary>
		/// <param name="script">A <see cref="ScriptBuilder"/> that creates the output stream to render jQuery JavaScript on the client.</param>
		protected virtual void RenderReadyScript(ScriptBuilder script) { }

		/// <summary>
		/// Renders a script to be executed on page startup.
		/// This method is used primarily by control developers.
		/// </summary>
		/// <param name="script">A <see cref="ScriptBuilder"/> that creates the output stream to render jQuery JavaScript on the client.</param>
		protected virtual void RenderStartupScript(ScriptBuilder script) { }

		/// <summary>
		/// Renders a script to be executed on form/postback submit.
		/// This method is used primarily by control developers.
		/// </summary>
		/// <param name="script">A <see cref="ScriptBuilder"/> that creates the output stream to render jQuery JavaScript on the client.</param>
		protected virtual void RenderSubmitScript(ScriptBuilder script) { }

		#endregion


		#region Methods: Rendering

		/// <summary>
		/// Raises the <see cref="Control.PreRender"/> event.
		/// </summary>
		/// <param name="e">The <see cref="EventArgs"/> object that contains the event data.</param>
		protected override void OnPreRender(EventArgs e) {

			//TODO: Find out if this can be moved to after the base call to make it later...
			Register(Manager.GetCurrent(Page));

			base.OnPreRender(e);
		}

		/// <summary>
		/// Allows a jQuery server control to reference scripts and stylesheets necessary to render their client markup and widgets.
		/// </summary>
		/// <param name="manager">The <see cref="Manager"/> used to handle style and script referencing in addition to unified generation of load and ready scripts.</param>
		protected virtual void Register(Manager manager) { }

		#endregion


		#region Explicit implementation: IManagedControl

		void IManagedControl.RenderReadyScript(ScriptBuilder script) {
			RenderReadyScript(script);
		}

		void IManagedControl.RenderStartupScript(ScriptBuilder script) {
			RenderStartupScript(script);
		}

		void IManagedControl.RenderSubmitScript(ScriptBuilder script) {
			RenderSubmitScript(script);
		}

		#endregion


	}

}